<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/1/26 0026
 * Time: 17:31
 */
namespace app\manager\model;


use app\common\helper\Obj2Array;
use app\common\model\Model;
use think\Db;
use think\Exception;

/**
 *  权限分配
 *
 * Class RolePermissionModel
 * @package app\manager\model
 */
class RolePermissionModel extends Model {
    const TYPE_PERMISSION = 1; // 普通权限
    const TYPE_MENU = 2; // 菜单权限

    public $error_msg = null;

    public static function typeList(){
        return [
            self::TYPE_MENU => '菜单权限',
            self::TYPE_PERMISSION => '普通权限',
        ];
    }

    /**
     * 将分配的权限入库
     *
     * @param $role_id
     * @param $data
     * @param $type
     * @return bool
     * @throws Exception
     */
    public function dispatch($role_id, $data, $type) {
        // 要分配的权限的格式化数组
        $data_insert = $this->dataForInsert($data, $role_id, $type);
        // 入库
        if (!$res = $this->deleteAndSave($data_insert, $role_id, $type)) {
            return false;
        }
        return true;
    }

    /**
     *
     * @param $data
     * @param $role_id
     * @param $type
     * @return array
     * @throws Exception
     */
    private function dataForInsert($data, $role_id, $type) {
        if (in_array($type,[self::TYPE_MENU, self::TYPE_PERMISSION])) {
            $list = [];
            foreach ($data as $key => $item) {
                $list[$key]['role_id'] = $role_id;
                $list[$key]['permission_id'] = $item;
                $list[$key]['type'] = $type;
            }
            return $list;
        } else {
            throw new Exception('没有该类型');
        }
    }

    /**
     * 将权限入库
     *
     * @param $data
     * @param $role_id
     * @param $type
     * @return bool
     */
    private function deleteAndSave($data, $role_id, $type) {
        $table = $this->getTable();
        $str = '';
        foreach ($data as $item) {
            $str .= '(' . implode(',', $item) . '),';
        }
        $str = rtrim($str, ',');
        $sql = "insert ignore into `{$table}`(`role_id`,`permission_id`,`type`)values{$str}";
        Db::startTrans();
        try {
            // 先删除所有以前的权限
            $this->where(['role_id' => $role_id, 'type' => $type])->delete();
            // 将分配的权限入库
            $res = Db::execute($sql);
            if ($res === false) {
                throw new Exception('分配失败！');
            }
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            $this->error_msg = $e->getMessage();
            return false;
        }
        return true;
    }

    /**
     * 菜单权限list
     * @param $role_id
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function menuPermissionList($role_id) {
        $modelM = new MenuModel();
        // 所有权限list
        $list = $modelM->field('p_id, id, level, title')->where(['status' => MenuModel::STATUS_OK])->order(['level' => 'ASC'])->select();
        if (!empty($list)) {
            $list = Obj2Array::resObject2Array($list);
        }
        // 获取该角色已经拥有的授权项
        $RPM = new RolePermissionModel();
        $has = $RPM->where(['type' => self::TYPE_MENU, 'role_id' => $role_id])->column('permission_id');
        return $list = $this->formatData($list, $has);
    }

    /**
     * 普通权限list
     * @param $role_id
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function permissionList($role_id) {
        $modelM = new PermissionModel();
        $list = $modelM->field('p_id, id, level, name')->where(['status' => PermissionModel::STATUS_OK])->order(['level' => 'ASC'])->select();
        if (!empty($list)) {
            $list = Obj2Array::resObject2Array($list);
        }
        // 获取该角色已经拥有的授权项
        $RPM = new RolePermissionModel();
        $has = $RPM->where(['type' => self::TYPE_PERMISSION, 'role_id' => $role_id])->column('permission_id');
        return $list = $this->permissionFormat($list, $has);
    }

    /**
     * 普通权限格式化
     * @param $list
     * @param $has_list
     * @return array
     */
    private function permissionFormat($list, $has_list) {
        if (!$list) {
            return $list;
        }
        $arr = [];
        //var_dump($list);
        foreach ($list as $li) {
            if (in_array($li['id'], $has_list)) {
                $li['had'] = 1;
            } else {
                $li['had'] = 0;
            }
            if ($li['level'] == PermissionModel::LEVEL_ONE) {
                $arr[$li['id']] = $li;
            } else if ($li['level'] == PermissionModel::LEVEL_TWO) {
                $arr[$li['p_id']]['child'][$li['id']] = $li;
            }
        }
        // 重组数组，用自然数索引组成新的数组
        return array_values($arr);
    }

    /**
     * 菜单权限list格式化
     *
     * @param $list
     * @param $has_list
     * @return array
     */
    private function formatData($list, $has_list) {
        if (!$list) {
            return $list;
        }

        $arr = [];
        //var_dump($list);
        foreach ($list as $li) {
            if (in_array($li['id'], $has_list)) {
                $li['had'] = 1;
            } else {
                $li['had'] = 0;
            }
            if ($li['level'] == MenuModel::LEVEL_ONE) {
                $arr[$li['id']] = $li;
            } else if ($li['level'] == MenuModel::LEVEL_TWO) {
                $arr[$li['p_id']]['child'][$li['id']] = $li;
            } else if ($li['level'] == MenuModel::LEVEL_THREE) {
                $arr[$this->findTopId($li['p_id'], $list)]['child'][$li['p_id']]['child'][] = $li;
            }
        }
        // 重组数组，用自然数索引组成新的数组
        return array_values($arr);
    }

    /**
     * 获取顶级菜单id
     *
     * @param $pid
     * @param $list
     * @return mixed
     */
    private function findTopId($pid, $list) {
        foreach ($list as $item) {
            if ($item['id'] == $pid) {
                return $item['p_id'];
            }
        }
    }
}